package com.wisenet.wx.tenpay.http.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletOutputStream;

import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.wisenet.common.WxConst;
import com.wisenet.wx.tenpay.http.HttpClientConnManager;
import com.wisenet.wx.util.SignUtil;

/**
 * 微信支付工具类
 * @author fzh
 *
 */
public class WeiXinPayUtil {
	// 日志
	private static final Logger logger = Logger.getLogger(WeiXinPayUtil.class);
	
	private static final int TIME_OUT = 10000;
	
	/**
	 * 统一下单
	 * @param xml
	 * @return
	 * @throws Exception
	 */
	public static SortedMap<String, String> unifiedOrder(String xml) throws Exception {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// 配置超时时间
		RequestConfig requestConfig = RequestConfig.custom()
				.setConnectTimeout(TIME_OUT).setConnectionRequestTimeout(TIME_OUT)
				.setSocketTimeout(TIME_OUT).setRedirectsEnabled(true).build();
		
		HttpPost httpPost = HttpClientConnManager.getPostMethod(WxConst.UNIFIEDORDER_URL);
		httpPost.setConfig(requestConfig);

		httpPost.setEntity(new StringEntity(xml, "UTF-8"));
		HttpResponse response = httpClient.execute(httpPost);
		
		String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
		
		logger.info("unifiedOrder resultXml: " + jsonStr);
		
		return XMLUtil.doXMLParse(jsonStr);
	}
	
	/**
	 * 商户server调用再次签名
	 * @param prepayId
	 * @param appid
	 * @param mchKey
	 * @return
	 */
	public static SortedMap<String, String> signAgain(String prepayId, String appId, String mchKey) {
		SortedMap<String, String> params = new TreeMap<String, String>();
		params.put("appId", appId);
		params.put("signType", WxConst.SIGNTYPE);
		params.put("package", "prepay_id=" + prepayId);
		params.put("nonceStr", SignUtil.getNonceStr(32));
		params.put("timeStamp", SignUtil.getTimeStamp());
		params.put("paySign", SignUtil.createSign(params, mchKey));
		return params;
	}
	
	/**
	 * 验证签名
	 * @param map
	 * @param mchKey
	 * @return
	 */
	public static boolean validateSignature(SortedMap<String, String> map, String mchKey) {
		String sign = SignUtil.createSign(map, mchKey);
		return sign.equals(map.get("sign"));
	}
	
	/**
	 * 获取回调报文xml
	 * @param reader
	 * @return
	 */
	public static SortedMap<String, String> getNotifyXml(BufferedReader reader) {
		String inputLine = "", notifyXml = "";
		try {
			// 接收回调报文
			while ((inputLine = reader.readLine()) != null) {
				notifyXml += inputLine;
			}
			logger.info("receive notifyXml: " + notifyXml);
			if ("".equals(notifyXml)) return null;

			// 解析回调结果
			return XMLUtil.doXMLParse(notifyXml);
		} catch (Exception e) {
			logger.info("error: " + e.getMessage());
		} finally {
			try {
				reader.close();
			} catch (IOException e) {
				logger.info("reader error: " + e.getMessage());
			}
		}
		return null;
	}
	
	/**
	 * 两位小数的金额
	 * @param money
	 * @return
	 */
	public static Double getMoney(double money) {
		DecimalFormat df = new DecimalFormat("0.00");
		return new Double(df.format(money).toString());
	}
	
	/**
	 * 将下划线转换为驼峰的形式，例如：user_name-->userName
	 * @param json
	 * @param clazz
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("deprecation")
	public static <T> T toCamelObject(String json, Class<T> clazz) throws IOException {
		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
		return mapper.readValue(json, clazz);
	}
	 
	/**
	 * 回调结果给微信
	 * @param resultXml
	 * @param outputStream
	 */
	public static void sendResultXmlToWX(String resultXml, ServletOutputStream outputStream) {
		try {
			BufferedOutputStream out = new BufferedOutputStream(outputStream);
			out.write(resultXml.getBytes());
			out.flush();
			out.close();
		} catch (IOException e) {
			logger.info("send resultXml to wx error: " + e.getMessage());
		}
	}
	
}
